// src-tauri/src/complete_bittorrent.rs
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::fs::{File, create_dir_all};
use std::io::{Write, Read};
use std::path::{Path, PathBuf};
use tokio::net::TcpStream;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

use crate::distributed_trust::DistributedTrustSystem;
use crate::trust_chain::ContentApproval;

#[derive(Serialize, Deserialize, Clone)]
pub struct TorrentFile {
    pub info_hash: String,
    pub name: String,
    pub total_length: u64,
    pub piece_length: u64,
    pub pieces: Vec<String>, // 分片SHA1哈希列表
    pub files: Vec<FileInfo>,
    pub trackers: Vec<String>,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct FileInfo {
    pub path: Vec<String>,
    pub length: u64,
    pub md5sum: Option<String>,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct DownloadProgress {
    pub info_hash: String,
    pub total_pieces: usize,
    pub downloaded_pieces: usize,
    pub downloaded_bytes: u64,
    pub total_bytes: u64,
    pub download_speed: f64,
    pub upload_speed: f64,
    pub connected_peers: usize,
    pub status: DownloadStatus,
}

#[derive(Serialize, Deserialize, Clone)]
pub enum DownloadStatus {
    Downloading,
    Seeding,
    Completed,
    Paused,
    Error(String),
}

pub struct CompleteBitTorrentService {
    active_downloads: HashMap<String, ActiveDownload>,
    downloaded_files: HashMap<String, PathBuf>,
    trust_system: DistributedTrustSystem,
    download_dir: PathBuf,
}

struct ActiveDownload {
    torrent_file: TorrentFile,
    progress: DownloadProgress,
    piece_status: Vec<PieceStatus>, // 每个分片的状态
    connected_peers: HashMap<String, PeerConnection>,
    downloaded_pieces: HashSet<usize>,
}

struct PeerConnection {
    peer_id: String,
    ip: String,
    port: u16,
    bitfield: Vec<bool>, // 对方拥有的分片
    socket: Option<TcpStream>,
    is_choked: bool,
    is_interested: bool,
}

#[derive(Clone)]
enum PieceStatus {
    Missing,
    Downloading,
    Downloaded,
    Verified,
}

impl CompleteBitTorrentService {
    pub fn new(download_dir: PathBuf, trust_system: DistributedTrustSystem) -> Self {
        // 确保下载目录存在
        let _ = create_dir_all(&download_dir);
        
        Self {
            active_downloads: HashMap::new(),
            downloaded_files: HashMap::new(),
            trust_system,
            download_dir,
        }
    }

    /// 开始下载torrent文件内容
    pub async fn start_file_download(
        &mut self,
        torrent_file: TorrentFile,
        content_approval: Option<ContentApproval>,
    ) -> Result<String, String> {
        let info_hash = torrent_file.info_hash.clone();
        
        // 验证内容是否被批准（如果提供了批准信息）
        if let Some(approval) = content_approval {
            if !self.trust_system.is_content_approved(&approval.content_hash).await {
                return Err("Content not approved for download".to_string());
            }
        }

        // 初始化下载状态
        let total_pieces = torrent_file.pieces.len();
        let progress = DownloadProgress {
            info_hash: info_hash.clone(),
            total_pieces,
            downloaded_pieces: 0,
            downloaded_bytes: 0,
            total_bytes: torrent_file.total_length,
            download_speed: 0.0,
            upload_speed: 0.0,
            connected_peers: 0,
            status: DownloadStatus::Downloading,
        };

        let piece_status = vec![PieceStatus::Missing; total_pieces];

        let active_download = ActiveDownload {
            torrent_file,
            progress,
            piece_status,
            connected_peers: HashMap::new(),
            downloaded_pieces: HashSet::new(),
        };

        self.active_downloads.insert(info_hash.clone(), active_download);

        // 开始下载过程
        self.start_download_process(&info_hash).await;

        Ok(info_hash)
    }

    /// 主要的下载流程
    async fn start_download_process(&mut self, info_hash: &str) {
        if let Some(download) = self.active_downloads.get_mut(info_hash) {
            // 1. 连接Tracker获取Peer列表
            if let Ok(peers) = self.connect_to_trackers(&download.torrent_file).await {
                // 2. 连接Peers
                for peer_info in peers {
                    self.connect_to_peer(info_hash, peer_info).await;
                }
            }

            // 3. 开始下载分片
            self.download_pieces(info_hash).await;
        }
    }

    /// 连接Tracker获取Peer列表
    async fn connect_to_trackers(&self, torrent_file: &TorrentFile) -> Result<Vec<PeerInfo>, String> {
        let mut peers = Vec::new();
        
        for tracker_url in &torrent_file.trackers {
            match self.query_tracker(tracker_url, &torrent_file.info_hash).await {
                Ok(tracker_peers) => peers.extend(tracker_peers),
                Err(e) => println!("Tracker {} error: {}", tracker_url, e),
            }
        }

        // 如果没有Tracker，使用DHT发现Peers
        if peers.is_empty() {
            peers = self.discover_peers_via_dht(&torrent_file.info_hash).await;
        }

        Ok(peers)
    }

    /// 查询Tracker
    async fn query_tracker(&self, tracker_url: &str, info_hash: &str) -> Result<Vec<PeerInfo>, String> {
        // 简化的Tracker查询实现
        // 实际实现需要处理HTTP/HTTPS/UDP Tracker协议
        
        let peer_info = PeerInfo {
            ip: "127.0.0.1".to_string(), // 示例
            port: 6881,
            peer_id: "example_peer_id".to_string(),
        };

        Ok(vec![peer_info])
    }

    /// 通过DHT发现Peers
    async fn discover_peers_via_dht(&self, info_hash: &str) -> Vec<PeerInfo> {
        // 使用之前实现的DHT功能发现Peers
        Vec::new() // 简化实现
    }

    /// 连接到Peer
    async fn connect_to_peer(&mut self, info_hash: &str, peer_info: PeerInfo) {
        if let Some(download) = self.active_downloads.get_mut(info_hash) {
            match TcpStream::connect(format!("{}:{}", peer_info.ip, peer_info.port)).await {
                Ok(socket) => {
                    // 发送BitTorrent握手
                    if self.perform_handshake(&socket, info_hash).await.is_ok() {
                        let peer_conn = PeerConnection {
                            peer_id: peer_info.peer_id,
                            ip: peer_info.ip,
                            port: peer_info.port,
                            bitfield: Vec::new(),
                            socket: Some(socket),
                            is_choked: true,
                            is_interested: false,
                        };

                        download.connected_peers.insert(peer_info.peer_id, peer_conn);
                        download.progress.connected_peers = download.connected_peers.len();
                    }
                }
                Err(e) => println!("Failed to connect to peer {}:{}: {}", peer_info.ip, peer_info.port, e),
            }
        }
    }

    /// 执行BitTorrent握手
    async fn perform_handshake(&self, socket: &TcpStream, info_hash: &str) -> Result<(), String> {
        // 简化的握手实现
        // 实际需要发送正确的握手消息格式
        Ok(())
    }

    /// 下载文件分片
    async fn download_pieces(&mut self, info_hash: &str) {
        if let Some(download) = self.active_downloads.get_mut(info_hash) {
            let total_pieces = download.torrent_file.pieces.len();
            
            for piece_index in 0..total_pieces {
                if self.should_download_piece(info_hash, piece_index) {
                    if let Err(e) = self.download_single_piece(info_hash, piece_index).await {
                        println!("Failed to download piece {}: {}", piece_index, e);
                    }
                }
            }
        }
    }

    /// 下载单个分片
    async fn download_single_piece(
        &mut self,
        info_hash: &str,
        piece_index: usize,
    ) -> Result<(), String> {
        if let Some(download) = self.active_downloads.get_mut(info_hash) {
            // 标记分片为下载中
            download.piece_status[piece_index] = PieceStatus::Downloading;

            // 寻找拥有此分片的Peer
            if let Some(peer_conn) = self.find_peer_with_piece(info_hash, piece_index) {
                // 请求分片数据
                if let Some(piece_data) = self.request_piece_from_peer(peer_conn, piece_index).await {
                    // 验证分片哈希
                    if self.verify_piece_hash(&download.torrent_file, piece_index, &piece_data) {
                        // 保存分片到文件
                        self.save_piece_to_file(info_hash, piece_index, &piece_data).await?;
                        
                        // 更新下载状态
                        download.downloaded_pieces.insert(piece_index);
                        download.piece_status[piece_index] = PieceStatus::Verified;
                        download.progress.downloaded_pieces = download.downloaded_pieces.len();
                        download.progress.downloaded_bytes += piece_data.len() as u64;

                        // 检查是否全部完成
                        if download.progress.downloaded_pieces == download.progress.total_pieces {
                            download.progress.status = DownloadStatus::Completed;
                            self.assemble_complete_file(info_hash).await?;
                        }

                        return Ok(());
                    } else {
                        return Err("Piece hash verification failed".to_string());
                    }
                }
            }

            // 如果没有找到合适的Peer或下载失败，重置状态
            download.piece_status[piece_index] = PieceStatus::Missing;
            Err("Failed to download piece".to_string())
        } else {
            Err("Download not found".to_string())
        }
    }

    /// 寻找拥有指定分片的Peer
    fn find_peer_with_piece(&self, info_hash: &str, piece_index: usize) -> Option<&PeerConnection> {
        self.active_downloads
            .get(info_hash)?
            .connected_peers
            .values()
            .find(|peer| {
                // 检查Peer的bitfield是否显示拥有此分片
                piece_index < peer.bitfield.len() && peer.bitfield[piece_index]
            })
    }

    /// 从Peer请求分片数据
    async fn request_piece_from_peer(
        &self,
        peer_conn: &PeerConnection,
        piece_index: usize,
    ) -> Option<Vec<u8>> {
        // 简化的分片请求实现
        // 实际需要发送BitTorrent协议消息
        Some(vec![0u8; 1024]) // 示例数据
    }

    /// 验证分片哈希
    fn verify_piece_hash(
        &self,
        torrent_file: &TorrentFile,
        piece_index: usize,
        piece_data: &[u8],
    ) -> bool {
        if piece_index < torrent_file.pieces.len() {
            let computed_hash = self.compute_sha1_hash(piece_data);
            computed_hash == torrent_file.pieces[piece_index]
        } else {
            false
        }
    }

    /// 计算SHA1哈希
    fn compute_sha1_hash(&self, data: &[u8]) -> String {
        use sha1::{Sha1, Digest};
        let mut hasher = Sha1::new();
        hasher.update(data);
        format!("{:x}", hasher.finalize())
    }

    /// 保存分片到临时文件
    async fn save_piece_to_file(
        &mut self,
        info_hash: &str,
        piece_index: usize,
        piece_data: &[u8],
    ) -> Result<(), String> {
        let piece_path = self.download_dir
            .join("pieces")
            .join(info_hash)
            .join(format!("piece_{}.tmp", piece_index));

        // 确保目录存在
        if let Some(parent) = piece_path.parent() {
            create_dir_all(parent)
                .map_err(|e| format!("Failed to create directory: {}", e))?;
        }

        let mut file = File::create(&piece_path)
            .map_err(|e| format!("Failed to create piece file: {}", e))?;

        file.write_all(piece_data)
            .map_err(|e| format!("Failed to write piece data: {}", e))?;

        Ok(())
    }

    /// 组装完整文件
    async fn assemble_complete_file(&mut self, info_hash: &str) -> Result<PathBuf, String> {
        if let Some(download) = self.active_downloads.get(info_hash) {
            let torrent_file = &download.torrent_file;
            let output_path = self.download_dir
                .join(&torrent_file.name);

            let mut output_file = File::create(&output_path)
                .map_err(|e| format!("Failed to create output file: {}", e))?;

            // 按顺序读取所有分片并写入最终文件
            for piece_index in 0..torrent_file.pieces.len() {
                let piece_path = self.download_dir
                    .join("pieces")
                    .join(info_hash)
                    .join(format!("piece_{}.tmp", piece_index));

                let mut piece_file = File::open(&piece_path)
                    .map_err(|e| format!("Failed to open piece file: {}", e))?;

                let mut piece_data = Vec::new();
                piece_file.read_to_end(&mut piece_data)
                    .map_err(|e| format!("Failed to read piece data: {}", e))?;

                output_file.write_all(&piece_data)
                    .map_err(|e| format!("Failed to write to output file: {}", e))?;
            }

            // 保存下载文件记录
            self.downloaded_files.insert(info_hash.to_string(), output_path.clone());

            Ok(output_path)
        } else {
            Err("Download not found".to_string())
        }
    }

    /// 获取下载进度
    pub fn get_download_progress(&self, info_hash: &str) -> Option<DownloadProgress> {
        self.active_downloads
            .get(info_hash)
            .map(|download| download.progress.clone())
    }

    /// 获取所有活跃下载
    pub fn get_all_downloads(&self) -> Vec<DownloadProgress> {
        self.active_downloads
            .values()
            .map(|download| download.progress.clone())
            .collect()
    }

    /// 暂停下载
    pub fn pause_download(&mut self, info_hash: &str) -> Result<(), String> {
        if let Some(download) = self.active_downloads.get_mut(info_hash) {
            download.progress.status = DownloadStatus::Paused;
            Ok(())
        } else {
            Err("Download not found".to_string())
        }
    }

    /// 恢复下载
    pub fn resume_download(&mut self, info_hash: &str) -> Result<(), String> {
        if let Some(download) = self.active_downloads.get_mut(info_hash) {
            download.progress.status = DownloadStatus::Downloading;
            // 重新开始下载过程
            let info_hash_clone = info_hash.to_string();
            tokio::spawn(async move {
                // 在实际实现中，这里需要重新启动下载流程
            });
            Ok(())
        } else {
            Err("Download not found".to_string())
        }
    }

    /// 获取下载的文件路径
    pub fn get_downloaded_file_path(&self, info_hash: &str) -> Option<PathBuf> {
        self.downloaded_files.get(info_hash).cloned()
    }

    fn should_download_piece(&self, info_hash: &str, piece_index: usize) -> bool {
        self.active_downloads
            .get(info_hash)
            .map(|download| {
                matches!(download.piece_status[piece_index], PieceStatus::Missing)
            })
            .unwrap_or(false)
    }
}

#[derive(Clone)]
struct PeerInfo {
    ip: String,
    port: u16,
    peer_id: String,
}